package com.cali.libcore.dialog

import android.app.Activity
import android.content.Context
import android.os.Build
import android.os.Bundle
import android.view.Gravity
import android.view.View
import android.view.WindowManager
import androidx.annotation.LayoutRes
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.FragmentManager
import com.cali.libcore.R


/**
 * Created by mq on 2018/9/1 上午10:57
 * mqcoder90@gmail.com
 */

class MyDialog : MyBaseDialog(), IDialog {
    override val mContext: Context by lazy {
        context!!
    }
    var controller: MyDialogController
    private var buildListener: IDialog.OnBuildListener? = null
    private var dismissListener: IDialog.OnDismissListener? = null

    override val layoutRes: Int
        get() = controller.layoutRes

    override val dialogView: View?
        get() = controller.dialogView

    init {
        controller = MyDialogController(this)
    }

    /**
     * 兼容6.0以下的某些版本 如（vivo x7、5.1.1系统）不走[.onAttach]方法，
     * 这里的Fragment用的不是v4包里面的
     *
     */
    
    override fun isCancelable(): Boolean {
        return controller.isCancelable
    }
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        controller = MyDialogController(this)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        //设置默认Dialog的View布局
        controller.setChildView(view)
        //回调给调用者，用来设置子View及点击事件等
        if (buildListener != null && baseView != null) {
            buildListener?.onBuildChildView(this, baseView!!, layoutRes)
        }
    }

    /**
     * 解决 Can not perform this action after onSaveInstanceState问题
     *
     * @param manager FragmentManager
     * @param tag     tag
     */
    fun showAllowingLoss(manager: FragmentManager, tag: String) {
        try {
            val cls = DialogFragment::class.java
            val mDismissed = cls.getDeclaredField("mDismissed")
            mDismissed.isAccessible = true
            mDismissed.set(this, false)
            val mShownByMe = cls.getDeclaredField("mShownByMe")
            mShownByMe.isAccessible = true
            mShownByMe.set(this, true)
        } catch (e: Exception) {
            //调系统的show()方法
            show(manager, tag)
            return
        }

        val ft = manager.beginTransaction()
        ft.add(this, tag)
        ft.commitAllowingStateLoss()
    }

    override fun dismiss() {
        //防止横竖屏切换时 getFragmentManager置空引起的问题：
        //Attempt to invoke virtual method 'android.app.FragmentTransaction
        //android.app.FragmentManager.beginTransaction()' on a null object reference
        if (fragmentManager == null) return
        super.dismissAllowingStateLoss()
    }

    override fun onDestroy() {
        //监听dialog的dismiss
        if (dismissListener != null) {
            dismissListener?.onDismiss(this)
        }
        super.onDestroy()
    }

    class Builder(activity: AppCompatActivity) {
        private val params: MyDialogController.SYParams = MyDialogController.SYParams()
        private var buildListener: IDialog.OnBuildListener? = null
        private var dismissListener: IDialog.OnDismissListener? = null

        init {
            params.fragmentManager = activity.supportFragmentManager
            params.context = activity
        }

        /**
         * 设置DialogView
         *
         * @param layoutRes 布局文件
         * @return Builder
         */
        fun setDialogView(@LayoutRes layoutRes: Int): Builder {
            params.layoutRes = layoutRes
            return this
        }

        /**
         * 设置DialogView
         *
         * @param dialogView View
         * @return Builder
         */
        fun setDialogView(dialogView: View): Builder {
            params.dialogView = dialogView
            return this
        }

        /**
         * 设置屏幕宽度百分比
         *
         * @param percentage 0.0f~1.0f
         * @return Builder
         */
        fun setScreenWidthP(percentage: Float): Builder {
            params.dialogWidth =
                (getScreenWidth(params.context as Activity) * percentage).toInt()
            return this
        }

        /**
         * 设置屏幕高度百分比
         *
         * @param percentage 0.0f~1.0f
         * @return Builder
         */
        fun setScreenHeightP(percentage: Float): Builder {
            params.dialogHeight = (getScreenHeight(params.context as Activity) * percentage).toInt()
            return this
        }

        /**
         * 设置Dialog的宽度
         *
         * @param width 宽度
         * @return Builder
         */
        fun setWidth(width: Int): Builder {
            params.dialogWidth = width
            return this
        }

        /**
         * 设置Dialog的高度
         *
         * @param height 高度
         * @return Builder
         */
        fun setHeight(height: Int): Builder {
            params.dialogHeight = height
            return this
        }

        /**
         * 设置背景色色值
         *
         * @param percentage 0.0f~1.0f 1.0f为完全不透明
         * @return Builder
         */
        fun setWindowBackgroundP(percentage: Float): Builder {
            params.dimAmount = percentage
            return this
        }

        /**
         * 设置Gravity
         *
         * @param gravity Gravity
         * @return Builder
         */
        fun setGravity(gravity: Int): Builder {
            params.gravity = gravity
            return this
        }

        /**
         * 设置dialog外点击是否可以让dialog消失
         *
         * @param cancelableOutSide true 则在dialog屏幕外点击可以使dialog消失
         * @return Builder
         */
        fun setCancelableOutSide(cancelableOutSide: Boolean): Builder {
            params.isCancelableOutside = cancelableOutSide
            return this
        }

        /**
         * 设置是否屏蔽物理返回键
         *
         * @param cancelable true 点击物理返回键可以让dialog消失；反之不消失
         * @return Builder
         */
        fun setCancelable(cancelable: Boolean): Builder {
            params.cancelable = cancelable
            return this
        }

        /**
         * 构建子View的listener
         *
         * @param listener IDialog.OnBuildListener
         * @return Builder
         */
        fun setBuildChildListener(listener: IDialog.OnBuildListener): Builder {
            this.buildListener = listener
            return this
        }

        /**
         * 监听dialog的dismiss
         *
         * @param dismissListener IDialog.OnDismissListener
         * @return Builder
         */
        fun setOnDismissListener(dismissListener: IDialog.OnDismissListener): Builder {
            this.dismissListener = dismissListener
            return this
        }

        /**
         * 设置dialog的动画效果
         *
         * @param animStyle 动画资源文件
         * @return Builder
         */
        fun setAnimStyle(animStyle: Int): Builder {
            params.animRes = animStyle
            return this
        }

        /**
         * 设置默认右侧点击按钮
         *
         * @param onclickListener IDialog.OnClickListener
         * @return Builder
         */
        fun setPositiveButton(onclickListener: IDialog.OnClickListener): Builder {
            return setPositiveButton("确定", onclickListener)
        }

        /**
         * 设置默认右侧点击按钮及文字
         *
         * @param onclickListener IDialog.OnClickListener
         * @return Builder
         */
        private fun setPositiveButton(btnStr: String, onclickListener: IDialog.OnClickListener): Builder {
            params.positiveBtnListener = onclickListener
            params.positiveStr = btnStr
            params.showBtnRight = true
            return this
        }

        /**
         * 设置左侧按钮
         *
         * @param onclickListener IDialog.OnClickListener
         * @return Builder
         */
        fun setNegativeButton(onclickListener: IDialog.OnClickListener): Builder {
            return setNegativeButton("取消", onclickListener)
        }

        /**
         * 设置左侧文字及按钮
         *
         * @param btnStr          文字
         * @param onclickListener IDialog.OnClickListener
         * @return Builder
         */
        private fun setNegativeButton(btnStr: String, onclickListener: IDialog.OnClickListener): Builder {
            params.negativeBtnListener = onclickListener
            params.negativeStr = btnStr
            params.showBtnLeft = true
            return this
        }

        /**
         * 设置默认dialog的title
         *
         * @param title 标题
         * @return Builder
         */
        fun setTitle(title: String): Builder {
            params.titleStr = title
            return this
        }

        /**
         * 设置默认dialog的内容
         *
         * @param content 内容
         * @return Builder
         */
        fun setContent(content: String): Builder {
            params.contentStr = content
            return this
        }

        private fun create(): MyDialog {
            val dialog = MyDialog()
            params.apply(dialog.controller)
            dialog.buildListener = buildListener
            dialog.dismissListener = dismissListener
            return dialog
        }

        /**
         * 展示Dialog
         *
         * @return MyDialog
         */
        fun show(): MyDialog {
            if (params.layoutRes <= 0 && params.dialogView == null) {
                //如果没有设置布局 提供默认设置
                setDefaultOption()
            }
            val dialog = create()
            //判空
            if (params.context == null) return dialog
            if (params.context is Activity) {
                val activity = params.context as Activity
                //如果Activity正在关闭或者已经销毁 直接返回
                val isRefuse = if (Build.VERSION.SDK_INT >= 17)
                    activity.isFinishing || activity.isDestroyed
                else
                    activity.isFinishing

                if (isRefuse) return dialog
            }
            removePreDialog()
            dialog.showAllowingLoss(params.fragmentManager!!, FTag)
            return dialog
        }

        /**
         * 设置默认Dialog的配置
         */
        private fun setDefaultOption() {
            params.cancelable = false
            params.isCancelableOutside = false
            params.gravity = Gravity.CENTER
            params.layoutRes = R.layout.lib_ui_layout_dialog_default
            params.dimAmount = 0.5f
            params.dialogWidth = (getScreenWidth(params.context as Activity) * 0.85f).toInt()
            params.dialogHeight = WindowManager.LayoutParams.WRAP_CONTENT
        }

        /**
         * 移除之前的dialog
         */
        private fun removePreDialog() {
            val ft = params.fragmentManager?.beginTransaction()
            val prev = params.fragmentManager?.findFragmentByTag(FTag)
            if (prev != null) {
                ft?.remove(prev)
            }
            ft?.commitAllowingStateLoss()
        }


    }

    companion object {
        private val FTag = "dialogTag"
    }


}
